package cn.com.sparkle.paxos.net.factory.netty;

import java.net.InetAddress;
import java.net.UnknownHostException;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import cn.com.sparkle.paxos.iomodel.protobuffmessage.PaxosMessages.MessagePackage;
import cn.com.sparkle.paxos.net.factory.NetHandler;
import cn.com.sparkle.paxos.net.factory.NetServer;


public class NettyServer implements NetServer{
	private ServerBootstrap bootstrap = new ServerBootstrap();
	@Override
	public void init(String confPath,final NetHandler handler) {
		
		NioEventLoopGroup group = new NioEventLoopGroup(3);
		bootstrap.group(group).channel(NioServerSocketChannel.class)
				.option(ChannelOption.TCP_NODELAY, true)
				.childHandler(new ChannelInitializer<SocketChannel>() {
					@Override
					public void initChannel(SocketChannel ch) throws Exception {
						ch.pipeline()
								.addLast(new DefaultEventExecutorGroup(10),
										new ProtobufVarint32FrameDecoder(),
										new ProtobufDecoder(
												MessagePackage.getDefaultInstance()),
										new ProtobufVarint32LengthFieldPrepender(),
										new ProtobufEncoder())
								.addLast(new NettyHandler(handler));
					}
				});
	}
	@Override
	public void listen(String ip, int port) throws Throwable {
		ChannelFuture f = bootstrap.bind(InetAddress.getByName(ip), port);
		f.await();
		if(!f.isSuccess()){
			throw f.cause();
		}
	}


}
